package com.shigen.demo.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.shigen.demo.bean.Result;
import com.shigen.demo.entity.Project;
import com.shigen.demo.entity.UserInfo;
import com.shigen.demo.entity.req.ProjectReq;
import com.shigen.demo.entity.req.ProjectDataReq.QueryItem;
import com.shigen.demo.entity.vo.ProjectVo;
import com.shigen.demo.exception.BusinessException;
import com.shigen.demo.mapper.ProjectMapper;
import com.shigen.demo.service.IProjectDataService;
import com.shigen.demo.service.IProjectService;
import com.shigen.demo.service.UserService;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.util.Date;
import java.util.List;
import java.util.Map;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

@Service
@Slf4j
public class ProjectServiceImpl extends ServiceImpl<ProjectMapper, Project> implements IProjectService {

  @Resource
  private IProjectDataService projectDataService;
  @Resource
  private UserService userService;

  @Override
  public Result getProject(String id) {
    if (StrUtil.isBlank(id)) {
      return null;
    }
    ProjectVo projectVo = getBaseMapper().getProjectDetail(id);

    if (projectVo != null) {
      Result<String> objectResult = this.verifyDate(projectVo.getBeginTime(), projectVo.getEndTime());
      if (objectResult != null) {
        return objectResult;
      }
      Boolean isStop = projectVo.getIsStop();
      if (isStop != null && isStop) {
        return Result.err("管理员已关闭此表单收集");
      }

      String list = projectVo.getList();
      String config = projectVo.getConfig();
      try {
        projectVo.setList1(JSONArray.parseArray(list));
        projectVo.setConfig1(JSONObject.parseObject(config));
      } catch (Exception e) {
        log.error("json数据解析失败，list: {} config: {}, exception: {}", list, config, e.getMessage());
      }
      return Result.ok(projectVo);
    }
    return Result.err("未查询到此表单");
  }

  @Override
  public int createProject(ProjectReq.OpBase opBase) {
    UserInfo userInfo = userService.getUserInfo();

    Project project = new Project()
        .setProjId(IdUtil.simpleUUID())
        .setProjName(opBase.getProjName())
        .setWriteOnce(opBase.isWriteOnce())
        .setBeginTime(DateUtil.parse(opBase.getBeginTime()))
        .setEndTime(DateUtil.parse(opBase.getEndTime()))
        .setTitle(opBase.getTitle())
        .setDescribe(opBase.getDescribe())
        .setList(opBase.getList())
        .setConfig(opBase.getConfig())
        .setCreateUserId(userInfo.getUserId())
        .setCreateUserName(userInfo.getUserName());
    return getBaseMapper().insert(project);
  }

  /**
   * 根据项目名或项目描述查询
   *
   * @param queryItem
   * @return
   */
  @Override
  public IPage<ProjectVo> getProjectList(ProjectReq.QueryItem queryItem) {
    Page<ProjectVo> page = new Page<>(queryItem.getPagenum(), queryItem.getPagesize());
    QueryWrapper<ProjectVo> voQueryWrapper = new QueryWrapper<>();
    String param = queryItem.getParam();

    if (StrUtil.isNotBlank(param)) {
      voQueryWrapper.likeRight("proj_name", param).or().likeRight("`describe`", param);
    }
    voQueryWrapper.eq("is_del", false);
    voQueryWrapper.orderByDesc("create_time");
    return getBaseMapper().getProjectList(page, voQueryWrapper);
  }

  @Override
  public int changeProjectStatus(String id, Boolean isStop) {
    Project project = lambdaQuery().eq(Project::getProjId, id).one();
    if (project != null) {
      boolean update = lambdaUpdate().set(Project::getIsStop, isStop).eq(Project::getProjId, id).update();
      return update ? 1 : 0;
    }
    return 0;
  }

  @Override
  public void downloadDatas(String id, HttpServletResponse response) {
    QueryItem queryItem = new QueryItem();
    queryItem.setId(id);
    queryItem.setPagenum(1L);
    queryItem.setPagesize(10000L);

    List<Map<String, Object>> maps = projectDataService.projectDataMap(queryItem);

    // 将数据集合封装成Excel对象
    ExcelWriter writer = ExcelUtil.getWriter(true);
    // 创建writer并且进行别名
    // writer.addHeaderAlias("murmur", "序号");

    // 设置所有列为自动宽度，不考虑合并单元格
    writer.autoSizeColumnAll();
    if (CollectionUtil.isNotEmpty(maps)) {
      // 下载的时候发现合并的表头多出一列
      writer.merge(maps.get(0).size() - 1, "表单填写详情");
      writer.write(maps, true);
    }

    try {
      // 获取输出流
      final OutputStream output = response.getOutputStream();
      response.setHeader("Content-disposition", "attachment;filename=" + URLEncoder.encode("表单填写详情.xlsx", "UTF-8"));
      response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
      writer.flush(output, true);
      writer.close();
      // 关闭资源
      IoUtil.close(output);
    } catch (IOException e) {
      log.error("EducationServiceImpl [export] 输出到响应流失败", e);
      throw new BusinessException("导出Excel异常");
    }
  }

  /**
   * 验证当前的时间是否在开始时间和结束时间之间
   *
   * @param beginTime
   * @param endTime
   * @return
   */
  Result<String> verifyDate(Date beginTime, Date endTime) {
    Date now = DateUtil.date();
    if (DateUtil.between(beginTime, now, DateUnit.SECOND) <= 0) {
      return Result.err("该表单还未开始收集");
    }
    if (DateUtil.between(endTime, now, DateUnit.SECOND) < 0) {
      return Result.err("该表单已经停止收集");
    }
    return null;
  }
}
